import { across, bet, section, tower } from '@prisma/client'
import { calcCurveY } from './ljMath'

// 装饰器
const scaleXYDecorator: MethodDecorator = (target, propertyKey, descriptor: PropertyDescriptor) => {
  const method = descriptor.value
  descriptor.value = (...args: any[]) => {
    const [x, y] = method(...args)
    return [x / 5, y * 2]
  }
}

export class CalcXY {
  constructor(
    private section: section,
    private towers: tower[],
    private bets: bet[],
    private lst_across: across[],
  ) {}

  /**
   * 获取铁塔的坐标
   * @param towers 铁塔的集合
   * @param func scale的方法
   */
  calcTowersXY() {
    const points = []
    for (const tower of this.towers) {
      tower.xy = JSON.stringify(this.calcTowerXY(tower))
      points.push(tower.xy)
    }
    return points
  }

  /**
   * 计算控制点的坐标
   */
  calcAcrosssXY() {
    for (const across of this.lst_across) {
      // calcAcrossXY采用装饰器，会让this缺少指向
      across.xy = JSON.stringify(this.calcAcrossXY(across, this.towers))
    }
  }

  /**
   * 计算曲线的坐标
   */
  calcCurveXYs(w: number) {
    for (const bet of this.bets) {
      this.calcSigleCurveXY(w, bet)
    }
  }

  /**
   * 计算单个铁塔的坐标
   * @param tower 铁塔
   * return 坐标
   */
  @scaleXYDecorator
  calcTowerXY(tower: tower) {
    const x = tower.leiSpan
    const y = tower.altitude
    return [x, y]
  }

  /**
   * 计算控制点的坐标
   * @param across 单个控制点
   * @param towers 铁塔集合
   * @returns 控制点的坐标
   */
  @scaleXYDecorator
  calcAcrossXY(across: across, towers: tower[]) {
    const [n1] = across.btName.split('--')
    const t1 = towers.find((t) => t.tName === n1)
    const x = t1.leiSpan + across.acrossX
    const y = across.acrossY
    return [x, y]
  }

  calcSigleCurveXY(w: number, bet: bet) {
    const btSPan = bet.btSpan
    const xys = []
    for (let index = 0; index < 50; index++) {
      const cx = (btSPan / 49) * index
      const h = bet.h
      const [n1] = bet.btName.split('--')
      const t1 = this.towers.find((t) => t.tName === n1)
      const y0 = t1.altitude
      const hi = t1.ph
      const leiSpan = t1.leiSpan
      xys.push(this.calcCurveXY(w, y0, h, btSPan, cx, hi, leiSpan))
    }
    bet.curvexy = JSON.stringify(xys)
  }

  @scaleXYDecorator
  calcCurveXY(w: number, y0: number, h: number, btSPan: number, x: number, hi: number, leiSpan: number) {
    const y = calcCurveY(w, y0, h, btSPan, x, hi)
    return [x + leiSpan, y]
  }

  /**
   *
   * @param towers 铁塔集合
   * @returns
   */
  calcWidthAndHeight = () => {
    const lst_x = []
    const lst_y = []
    for (const tower of this.towers) {
      const [x, y] = JSON.parse(tower.xy)
      lst_x.push(x)
      lst_y.push(y)
    }
    const minx = Math.min(...lst_x)
    const maxx = Math.max(...lst_x)
    const miny = Math.min(...lst_y)
    const maxy = Math.max(...lst_y)

    const minXY = [minx, miny]
    const maxXY = [maxx, maxy]

    this.section.minXY = JSON.stringify(minXY)
    this.section.maxXY = JSON.stringify(maxXY)
  }
}
